<?php

/**
 * Description: 获取试卷题目
 * User: devforma
 * Date: 15/4/8
 * Time: 16:36
 */

require __DIR__ . '/includes/utils.php';
class HistoryExerciseDetail implements iController {

    //内部人员不计入统计
    private $excludeUsers = [910696, 641223, 886171, 1187197];

    /**
     * api请求处理主函数
     * @param array $queryArgs 就是$_REQUEST变量
     * @return array api返回结果，必须含response_code
     */
    public function output($queryArgs) {
        global $cmsdb;

        $typeArray = array(
            'mokao' => '天天模考',
            'entire' => '整卷练习',
            'auto' => '快速练习',
            'note' => '专项练习',
            'error' => '错题练习',
            'collect' => '收藏练习',
            'evaluate' => '估分',
            'mock' => '模考'
        );

        if (!isset($typeArray[$queryArgs['exercise_type']]))
            return genOutput(1000);

        $sql = 'SELECT * FROM `qb_relationship_user_paper` WHERE `id`=:exercise_id';
        $exercise = $cmsdb->getRow($sql, array(':exercise_id' => $queryArgs['exercise_id']));

        if (empty($exercise)) {
            return genOutput(1000);
        }

        //是否为只看错题
        if (!empty($queryArgs['only_error']) && $queryArgs['only_error'] == 'true')
            $onlyError = true;
        else
            $onlyError = false;

        if (in_array($queryArgs['exercise_type'], array('entire', 'mock', 'evaluate'), true)) { //整卷类试卷

            $category = array();
            if (($userData = json_decode($exercise->question_info)) && is_array($userData)) {
                foreach ($userData as $q) {
                    if ($onlyError && $q->is_right)
                        continue;

                    if (!isset($category[$q->category]))
                        $category[$q->category] = array(
                            'id' => intval($q->category),
                            'name' => getQuestionCategory($q->category),
                            'questions' => array(),
                            'answers' => array(),
                            'right_count' => 0,
                            'done_count' => 0,
                            'done_ids' => array()
                        );

                    $category[$q->category]['questions'][] = $q->id;
                    $category[$q->category]['answers'][] = array(
                        'id' => intval($q->id),
                        'is_right' => $q->is_right ? true : false,
                        'answer' => $q->answer,
                        'category' => intval($q->category),
                        'duration' => intval($q->duration),
                    );

                    if ($q->is_right)
                        $category[$q->category]['right_count']++;

                    if (!empty($q->answer)) {
                        $category[$q->category]['done_count']++;
                        $category[$q->category]['done_ids'][] = $q->id;
                    }
                }

                /* 2015-10-28 模考试卷题目增加缓存 */
                if (isset($_GET['original']) && $_GET['original'] == '1') {
                    $cacheKey = 'mock:paper:original:' . $exercise->paper_id;
                } else {
                    $cacheKey = 'mock:paper:' . $exercise->paper_id;
                }
                $paperCache = !$onlyError && $queryArgs['exercise_type'] === 'mock' ? cacheGet($cacheKey) : false;

                $i = 0;
                foreach ($category as $index => &$cat) {

                    if ($paperCache) {
                        $cat['questions'] = $paperCache['category'][$i++]['questions'];
                    } else {
                        $queryArgs['ids']           = $cat['questions'];
                        $queryArgs['is_paper']      = true;
                        $cat['questions']           = getQuestionsAndNotesByIds($queryArgs);
                    }
                    $cat['done_ids'] = implode(',', $cat['done_ids']);
                }

            } else {
                return genOutput(1001);
            }

            if ($exercise->status == 0)
                $status = 'fresh';
            elseif ($exercise->status == 1)
                $status = 'done';
            else
                $status = 'undone';

            /* 2015-10-27 练习分数增加版本控制 */
            if ($_GET['terminal_type'] === 'android_phone' && version_cmp($_GET['app_version'], '1.2.6') < 0) {
                $score = intval($exercise->evaluate);
            } else {
                $score = round($exercise->evaluate, 1);
            }

            $duration = $queryArgs['exercise_type'] === 'mock' ? 120*60 :
                intval($cmsdb->getVar('SELECT `duration` FROM `original_ztk_papers` WHERE `id`=' . $exercise->paper_id));

            /* 2015-12-21 整卷练习增加平均分和排名 */
            $avgScore = 0.0;
            $defeat = 0.0;
            if ($queryArgs['exercise_type'] === 'entire' && !empty($exercise->tmp_rank) && ($rank = json_decode($exercise->tmp_rank))) {
                $avgScore = $rank[0];
                $defeat = $rank[1];
            }

            $output = [
                'exercise_name' => $exercise->paper_title,
                'status' => $status,
                'duration' => $duration,
                'start_from' => intval($exercise->duration),
                'category' => array_values($category),
                'notes' => empty($exercise->note_info) ? array() : unserialize($exercise->note_info),
                'score' => $score,
                'defeat' => $defeat,
                'avg_score' => $avgScore,
                'scores' => empty($exercise->extra_info) ? array() : unserialize($exercise->extra_info)
            ];

            //模考,增加排名逻辑,模考5分钟之后才出排名
            if ($queryArgs['exercise_type'] === 'mock'
                && ($mockInfo = getMockInfo($exercise->paper_id))
                && ($mockDetail = unserialize($mockInfo->paper_customed_detail))) {

                //多试卷特殊处理
                if (!empty($mockInfo->papers)) {
                    $paperIdStr = implode(',', [$exercise->paper_id, $mockInfo->papers]);
                } else {
                    $paperIdStr = $exercise->paper_id;
                }

                $endTime = strtotime($mockDetail['startTime']) + $mockInfo->duration;
                if (time() > $endTime + 5*60) {
                    $mockRank = $this->getMockRank($exercise->paper_id, $paperIdStr, $exercise->evaluate);

                    $output['mock_rank'] = [
                        'available' => true,
                        'rank_info' => $mockRank
                    ];
                } else {
                    $output['mock_rank'] = [
                        'available' => false,
                        'available_time' => date('Y-m-d H:i:s', $endTime + 5*60)
                    ];
                }
            }

            return genOutput(1, $output);

        } else { //非整卷

            $answers = array();
            $qids = array();
            if (($questions = json_decode($exercise->question_info)) && is_array($questions)) {
                foreach ($questions as $q) {
                    if ($onlyError && $q->is_right)
                        continue;
                    
                    $answers[] = array(
                        'id'        => intval($q->id),
                        'is_right'  => $q->is_right ? true : false,
                        'answer'    => $q->answer,
                        'category'  => intval($q->category),
                        'duration'  => intval($q->duration),
                    );
                    $qids[] = $q->id;
                }
            } else {
                return genOutput(1001);
            }

            if ($exercise->status == 0)
                $status = 'fresh';
            elseif ($exercise->status == 1)
                $status = 'done';
            else
                $status = 'undone';

            //笔记
            $queryArgs['ids']         = $qids;
            $questionsData            = getQuestionsAndNotesByIds($queryArgs);

            return genOutput(1, array(
                'exercise_name' => $exercise->paper_title,
                'status' => $status,
                'duration' => 900,
                'start_from' => intval($exercise->duration),
                'questions' => $questionsData,
                'answers' => $answers,
                'notes' => empty($exercise->note_info) ? array() : unserialize($exercise->note_info),
                'score' => 0,
                'defeat' => $status === 'done' && $exercise->paper_type == '1'
                    ? $this->getMiniMokaoRank($exercise->paper_id, $exercise->evaluate) : 0.0,
                'scores' => array()
            ));

        }

    }

    /**
     * 获取mini模考排名信息
     * @param int $paperId mini模考id
     * @param float $score 待比较分数
     * @return float
     */
    private function getMiniMokaoRank($paperId, $score) {
        global $cmsdb;

        $rankScore = intval($score);

        //获取模考日期
        $miniMockDate = $cmsdb->getVar('SELECT `publish_date` FROM `qb_paper_mokao` WHERE `id`=:id', array(':id' => $paperId));

        //通过缓存获取模考信息
        $miniMockInfo = getMiniMockInfo($miniMockDate);

        //计算击败了多少
        $rank = $miniMockInfo['rank'];
        $total = $lower = 0;
        foreach ($rank as $score => $persons) {
            $total += $persons;
            if ($score < $rankScore) {
                $lower += $persons;
            }
        }

        return round($lower/$total, 2);
    }


    /**
     * 获取模考排名
     *
     * @param int $mockId 模考id
     * @param string $paperIdStr 试卷id字符串
     * @param float $userScore 用户分数
     * @return array
     */
    private function getMockRank($mockId, $paperIdStr, $userScore) {
        global $cmsdb;

        $cacheKey = 'func:getMockRank:'.$mockId;
        if (($result = cacheGet($cacheKey)) == null) {
            $exculdes = implode(',', $this->excludeUsers);
            $scores = $cmsdb->getCol("SELECT `evaluate` FROM `qb_relationship_user_paper` WHERE `paper_id` IN ({$paperIdStr}) AND `user_id` NOT IN ({$exculdes}) AND `paper_type`=8");

            $avgScore = round(array_sum($scores) / count($scores), 1);

            $result = [$scores, $avgScore];

            cacheAdd($cacheKey, $result, 48*60*60);
        }

        $lowerCount = $topScore = 0;
        foreach ($result[0] as $sc) {
            if ($sc < $userScore && $sc > 0) $lowerCount++;
            if ($sc > $topScore) $topScore = $sc;
        }

        return [
            'top' => (float)$topScore,
            'avg' => (float)$result[1],
            'defeat' => round($lowerCount/count($result[0]), 2)
        ];
    }
}